package com.xindao.xml;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.util.Base64;
import android.util.Xml;

public class XmlParser {

	public static void parseXml(InputStream ins, String encoding, Object obj)
			throws XmlPullParserException, IllegalArgumentException,
			UnsupportedEncodingException, IllegalAccessException, IOException {
		XmlPullParser parser = Xml.newPullParser(); // ����һ��Xml������
		parser.setInput(ins, encoding); // �������������ַ����
		parseXml(parser, obj); // �����ĵ�
		ins.close(); // �ر�������
	}

	private static void parseXml(XmlPullParser parser, Object obj)
			throws XmlPullParserException, IllegalArgumentException,
			UnsupportedEncodingException, IllegalAccessException, IOException {

		final String tag_value = "value";

		Class<?> cls = obj.getClass(); // ��ȡ��������ʱ��
		String clsName = cls.getName(); // ��ȡ�������

		Field[] fields = cls.getDeclaredFields(); // �����������������ֶ�

		Field field = null;

		int tagDepth; // ��ǩ���
		String tagName; // ��ǩ���
		int eventType = parser.getEventType(); // ��ȡ�¼�����
		while (true) {
			if (eventType == XmlPullParser.START_DOCUMENT) {
				// Log.i("START_DOCUMENT", "=START_DOCUMENT");
			} else if (eventType == XmlPullParser.START_TAG) {
				// Log.i("START_TAG", "=START_TAG");

				tagDepth = parser.getDepth(); // ��ȡ��ǩ���
				tagName = parser.getName(); // ��ȡ��ǩ���

				if (tagDepth == 1) { // һ����ǩ
					if (!tagName.equals(clsName)) { // �������Ʋ�һ��ʱ
						throw new XmlPullParserException("XML�ױ�ǩ���������Ʋ�һ��");
					}
				} else if (tagDepth == 2) { // ������ǩ
					// �жϱ�ǩ����Ƿ������ĳһ�ֶ����
					field = hasField(tagName, fields);
				} else if (tagDepth == 3 && field != null) { // ���ǩ
					if (tagName.equals(tag_value)) { // �����value��ǩ
						setValue(obj, field, parser.nextText());
						field = null;
					}
				}
			} else if (eventType == XmlPullParser.END_TAG) {
				// Log.i("END_TAG", "=END_TAG");
			} else if (eventType == XmlPullParser.TEXT) {
				// Log.i("TEXT", "=TEXT");
			} else if (eventType == XmlPullParser.END_DOCUMENT) {
				// Log.i("END_DOCUMENT", "=END_DOCUMENT");
				break;
			}
			eventType = parser.next(); // ��һ�����¼�
		}
	}

	private static Field hasField(String tagName, Field[] fields) {
		for (Field field : fields) {
			if (tagName.equals(field.getName())) {
				return field;
			}
		}
		return null;
	}

	private static void setValue(Object obj, Field field, String value)
			throws IllegalArgumentException, IllegalAccessException,
			UnsupportedEncodingException {
		Class<?> type = field.getType(); // ��������
		String typeName = type.getName(); // ������
		field.setAccessible(true); // ���ñ����ɷ���
		if (type.isPrimitive()) { // �Ƿ�Ϊ������
			if (typeName.equals("boolean")) {
				field.setBoolean(obj, Boolean.parseBoolean(value));
			} else if (typeName.equals("char")) {
				if (!value.equals("null")) {
					field.setChar(obj, value.charAt(0));
				}
			} else if (typeName.equals("byte")) {
				field.setByte(obj, Byte.parseByte(value));
			} else if (typeName.equals("short")) {
				field.setShort(obj, Short.parseShort(value));
			} else if (typeName.equals("int")) {
				field.setInt(obj, Integer.parseInt(value));
			} else if (typeName.equals("long")) {
				field.setLong(obj, Long.parseLong(value));
			} else if (typeName.equals("float")) {
				field.setFloat(obj, Float.parseFloat(value));
			} else if (typeName.equals("double")) {
				field.setDouble(obj, Double.parseDouble(value));
			}
		} else if (typeName.equals("java.lang.String")) { // �Ƿ�ΪString
			if (!value.equals("null")) {
				field.set(obj, value);
			}
		} else if (typeName.equals("[B")) { // �Ƿ�Ϊbyte[]
			if (!value.equals("null")) {
				// ��Base64���ַ�ת��byte[]��SDK 2.2֮���Դ�
				field.set(obj, Base64.decode(value, Base64.DEFAULT));
			}
		} // ���������ݲ���Ҫ
	}

}